"use strict";
// 向导表单
let EWizard = function (selector, options) {
    // 目标元素
    let the = this;

    // 查找对象
    let $element = $(selector);

    if (!$element.length) {
        return;
    }

    // 默认设置
    let defaultOptions = {
        startStep: 1
    };

    // 私有方法
    let Plugin = {
        construct: function (options) {
            if (EUtil.data($element).has('sample')) {
                // 如果已经初始化，直接从缓存获取对象
                the = EUtil.data($element).get('sample');
            } else {
                // 初始化插件
                Plugin.init(options);
                // 绑定事件
                Plugin.build();
                EUtil.data($element).set('sample', the);
            }
            return the;
        },

        /**
         * 初始化
         *
         * @param options {object} option
         */
        init: function (options) {
            // 事件
            the.events = [];

            // handlers
            the.eventHandlers = {};

            // 合并默认选项&传入option
            the.options = $.extend(true, {}, defaultOptions, options);

            // 操作按钮
            the.btn = {
                next: $element.find('.wizard-btn-next'),
                prev: $element.find('.wizard-btn-prev'),
                submit: $element.find('.wizard-btn-submit')
            };
            // 向导内容
            the.steps = $element.find('.e-wizard-step');
            the.navs = $element.find('.e-wizard-nav-item');

            // 当前 step
            the.currentStep = 1;
            // 共计 step
            the.totalSteps = the.steps.length;
            the.stoped = false;

            if (the.options.startStep > 1) {
                Plugin.goToStep(the.options.startStep);
            } else {
                Plugin.updateUI();
            }
        },
        /**
         * 绑定事件
         */
        build: function () {
            the.btn.next.click(Plugin.goNext);
            the.btn.prev.click(Plugin.goPrev);
            // 点击导航
            the.navs.click(function () {
                let clickStep = $(this).index() + 1;
                if (clickStep !== the.currentStep) {
                    Plugin.goToStep(clickStep);
                }
            });
        },
        /**
         * 停止
         */
        stop: function () {
            the.stopped = true;
        },

        /**
         * 开始
         */
        start: function () {
            the.stopped = false;
        },
        /**
         * 转到上一步
         */
        goPrev: function () {
            return Plugin.goToStep(Plugin.getPrevStep());
        },

        /**
         * 转到下一步
         */
        goNext: function () {
            return Plugin.goToStep(Plugin.getNextStep());
        },

        /**
         * 转到最后一步
         */
        goLast: function () {
            return Plugin.goToStep(the.totalSteps);
        },

        /**
         * 转到第一步
         */
        goFirst: function () {
            return Plugin.goToStep(1);
        },

        /**
         * 获取上一步 step
         */
        getPrevStep: function () {
            if ((the.currentStep - 1) >= 1) {
                return the.currentStep - 1;
            } else {
                return 1;
            }
        },

        /**
         * 获取下一步 step
         */
        getNextStep: function () {
            if (the.totalSteps >= (the.currentStep + 1)) {
                return the.currentStep + 1;
            } else {
                return the.totalSteps;
            }
        },

        /**
         * 转到指定的step
         *
         * @param stepIndex {number} step index （从1开始）
         * @return {*}
         */
        goToStep: function (stepIndex) {
            if (the.stoped) {
                // 被停止
                return;
            }

            if (!stepIndex || stepIndex === the.currentStep || stepIndex > the.totalSteps) {
                return;
            }

            let callback = null;
            let currentStep = the.steps[the.currentStep - 1];

            // 这里验证是否调用过回调，以免用户在beforeNext/beforePrev中调用wizard.goToStep导致死循环
            if(!$element.hasClass('already-called')){
                $element.addClass('already-called');
                // 调用触发事件
                if (stepIndex < the.currentStep) {
                    // 上一步
                    callback = Plugin.eventTrigger('beforePrev', currentStep);
                } else {
                    callback = Plugin.eventTrigger('beforeNext', currentStep);
                }
            }

            if (callback !== false) {
                Plugin.eventTrigger('beforeChange', currentStep);

                the.currentStep = stepIndex;

                Plugin.updateUI();

                Plugin.eventTrigger('change', currentStep);
            }
            if (stepIndex < the.currentStep) {
                // 上一步
                Plugin.eventTrigger('afterPrev', currentStep);
            } else {
                Plugin.eventTrigger('afterNext', currentStep);
            }
            $element.removeClass('already-called');
            return the;
        },
        /**
         * 更改 ui
         */
        updateUI: function () {
            $element.removeClass('already-called');

            let wizardStatus = null;

            if (Plugin.isFirstStep()) {
                wizardStatus = 'first'
            } else if (Plugin.isLastStep()) {
                wizardStatus = 'last'
            } else {
                wizardStatus = 'between'
            }
            // 设置向导状态
            $element.attr('data-wizard-status', wizardStatus);

            let length = the.totalSteps;
            let currentIndex = the.currentStep - 1;
            while (length--) {
                let stepStatus = null;
                if (length === currentIndex) {
                    // 当前激活
                    stepStatus = 'current';
                } else {
                    if (length < currentIndex) {
                        // 已填
                        stepStatus = 'done';
                    } else {
                        stepStatus = 'pending';
                    }
                }
                $(the.steps[length]).attr('data-step-status', stepStatus);
                $(the.navs[length]).attr('data-step-status', stepStatus);
            }
        },

        /**
         * 是否为第一步
         *
         * @returns {boolean} true/false
         */
        isFirstStep: function () {
            return the.currentStep === 1;
        },

        /**
         * 是否为中间步数
         *
         * @returns {boolean} true/false
         */
        isBetweenStep: function () {
            return Plugin.isLastStep() === false && Plugin.isFirstStep() === false;
        },
        /**
         * 是否为最后一步
         *
         * @returns {boolean} true/false
         */
        isLastStep: function () {
            return the.currentStep === the.totalSteps;
        },

        /**
         * 触发事件
         *
         * @param name {string} 事件名称
         * @param args {object} 参数
         * @return {*} 如果有多个事件，以最后一个事件返回值为准
         */
        eventTrigger: function (name, args) {
            let result = null;
            for (let i = 0; i < the.events.length; i++) {
                let event = the.events[i];
                if (event.name === name) {
                    if (event.one) {
                        // 一次性事件
                        if (!event.fired) {
                            // 设置事件属性为已触发，下次不执行
                            the.events[i].fired = true;
                            result = event.handler.call(this, the, args);
                        }
                    } else {
                        result = event.handler.call(this, the, args);
                    }
                }
            }
            return result;
        },

        /**
         * 添加事件
         *
         * @param name {string} 事件名称
         * @param handler {function} 回调
         * @param one {boolean} 是否一次性
         */
        addEvent: function (name, handler, one) {
            the.events.push({
                name: name,
                handler: handler,
                one: one,
                fired: false
            });
        },
        /**
         * 移除事件
         *
         * @param name {string} 事件名称
         */
        removeEvent: function (name) {
            if (the.events[name]) {
                delete the.events[name];
            }
        }
    };

    // 公开方法

    /**
     * 设置默认option
     *
     * @param options {object} 选项
     */
    the.setDefaults = function (options) {
        defaultOptions = options;
    };

    /**
     * 转到下一步
     */
    the.goNext = function () {
        return Plugin.goNext();
    };

    /**
     * 转到上一步
     */
    the.goPrev = function () {
        return Plugin.goPrev();
    };

    /**
     * 转到最后一步
     */
    the.goLast = function () {
        return Plugin.goLast();
    };

    /**
     * 停止
     */
    the.stop = function () {
        return Plugin.stop();
    };

    /**
     * 开始
     */
    the.start = function () {
        return Plugin.start();
    };

    /**
     * 转到第一步
     */
    the.goFirst = function () {
        return Plugin.goFirst();
    };

    /**
     * 转到指定的step
     *
     * @param stepIndex {number} step index
     * @return {*}
     */
    the.goToStep = function (stepIndex) {
        return Plugin.goToStep(stepIndex);
    };

    /**
     * 获取当前步数
     *
     * @returns {number} step
     */
    the.getStep = function () {
        return the.currentStep;
    };

    /**
     * 是否为最后一步
     *
     * @returns {boolean} true/false
     */
    the.isLastStep = function () {
        return Plugin.isLastStep();
    };

    /**
     * 是否为第一步
     *
     * @returns {boolean} true/false
     */
    the.isFirstStep = function () {
        return Plugin.isFirstStep();
    };

    /**
     * 绑定事件
     *
     * @param name {string} 事件名称
     * @param handler {function} 回调
     * @returns {*|void}
     */
    the.on = function (name, handler) {
        return Plugin.addEvent(name, handler, false);
    };
    /**
     * 绑定一次性事件
     *
     * @param name {string} 事件名称
     * @param handler {function} 回调
     * @returns {*|void}
     */
    the.one = function (name, handler) {
        return Plugin.addEvent(name, handler, true);
    };

    Plugin.construct.apply(the, [options]);
    return the;
};